package cn.sang.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;


import org.apache.commons.fileupload.disk.DiskFileItem;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

public class FileUtils {
	
	/**
	 * 上传文件工具类
	 */
	public static Map<String, Object> uploadFile(HttpServletRequest request,MultipartFile file, String uploadPath)
			throws IllegalStateException, IOException {

		Map<String, Object> jsonMap = new HashMap<String, Object>();

		if (file.isEmpty()) {
			jsonMap.put("success", false);
			jsonMap.put("msg", "fileEmpty");
			return jsonMap;
		}

		// 获取文件名
		String fileName = file.getOriginalFilename();

		// 获取文件后缀
		String suffix = fileName.substring(fileName.lastIndexOf("."),fileName.length());

		// 创建相对路径
		String relativePath = "/../data/res/static/" + uploadPath;
		String jdbcPath = "/data/res/static/" + uploadPath;

		String realPath = request.getSession().getServletContext().getRealPath(relativePath);
		if (realPath == null) {
			realPath = request.getSession().getClass().getClassLoader().getResource(relativePath).getPath();
		}

		// 创建文件夹
		File uploadDir = new File(realPath);

		if (!uploadDir.exists()) {
			uploadDir.mkdirs();
		}

		// 将MultipartFile 转成File,并获取MD5值
		CommonsMultipartFile cf = (CommonsMultipartFile) file;
		DiskFileItem fi = (DiskFileItem) cf.getFileItem();
		File f = fi.getStoreLocation();
		String md5ByFile = fileToMD5(f);

		// 上传
		File uploadFile = new File(realPath + "/" + md5ByFile + suffix);
		file.transferTo(uploadFile);

		String url = relativePath + "/" + md5ByFile + suffix;// 文件的相对路径
		String jdbcUrl = jdbcPath + "/" + md5ByFile + suffix;// 文件的存储

		jsonMap.put("success", true);
		jsonMap.put("url", url);
		jsonMap.put("jdbcUrl", jdbcUrl);
		jsonMap.put("realPath", uploadFile.getPath());
		jsonMap.put("file", uploadFile);
		jsonMap.put("md5ByFile", md5ByFile);
		return jsonMap;
	}
	
    /** 
     * 通过MD5加密文件 
     * @param inputFile 文件路径 
     * @return 已经通过MD5算法加密的32位字符串 
     */  
    public final static String fileToMD5(File inputFile) {  
        int bufferSize = 256 * 1024;// 定义缓冲区大小  
        FileInputStream fileInputStream = null;  
        DigestInputStream digestInputStream = null;  
        try {  
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");  
            fileInputStream = new FileInputStream(inputFile);  
            digestInputStream = new DigestInputStream(fileInputStream, messageDigest);  
            byte[] buffer = new byte[bufferSize];  
            while (digestInputStream.read(buffer) > 0)
            messageDigest = digestInputStream.getMessageDigest();  
            byte[] resultByteArray = messageDigest.digest();  
            return byteArrayToHex(resultByteArray);  
        } catch (Exception e) {  
        } finally {  
            try {  
                digestInputStream.close();  
            } catch (Exception e2) {  
            }  
        }  
        return null;  
    }
    
    /** 
     * @param byteArray 
     *                  byte数组 
     * @return 转后后的32位的字符串 
     */  
    private static String byteArrayToHex(byte[] byteArray) {  
        // 首先初始化一个字符数组，用来存放每个16进制字符  
        char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };  
  
        // new一个字符数组，这个就是用来组成结果字符串的（解释一下：一个byte是八位二进制，也就是2位十六进制字符（2的8次方等于16的2次方））  
        char[] resultCharArray = new char[byteArray.length * 2];// 每个字节用 16 进制表示的话，使用两个字符  
  
        // 遍历字节数组，通过位运算（位运算效率高），转换成字符放到字符数组中去  
        int index = 0;  
        // 从第一个字节开始，对MD5的每一个字节转换成16进制字符的转换  
        for (byte b : byteArray) {  
            // 取字节中高 4 位的数字转换  
            //>>> 为逻辑右移（即无符号右移），将符号位一起右移  
            resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];  
            // 取字节中低4位的数字转换   
            resultCharArray[index++] = hexDigits[b & 0xf];  
        }  
        // 字符数组组合成字符串返回  
        return new String(resultCharArray);  
    }  
	
}
